import os
# 设置Django环境
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mypro.settings')  # 替换为你的实际设置路径

import django
django.setup()

import os
from datetime import datetime, timedelta
import random
from typing import Dict, Any, Optional, List
from langchain.tools import tool
from langchain.agents import AgentExecutor, create_openai_functions_agent
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder, HumanMessagePromptTemplate
from langchain_core.messages import SystemMessage
from langchain_openai import ChatOpenAI
from mytools import vector_store_tools
from langchain.tools.retriever import create_retriever_tool

# 导入模型并设置别名避免冲突
from orders import models as orders_models
from login import models as login_models
from goods import models as goods_models

current_dir = os.path.dirname(os.path.abspath(__file__))
path = os.path.join(current_dir, "../../mypro/my_file/my_text.txt")
path = os.path.normpath(path)

retriever = vector_store_tools.VectorStoreTools(path).get_retriever('hetong')

retriever_tool = create_retriever_tool(
    retriever=retriever,
    name="insurance_clause_retriever",
    description="从保险条款库中检索相关条款内容，用于合同生成和审核参考"
)

# 初始化LLM
llm = ChatOpenAI(
    api_key=os.getenv('DASHSCOPE_API_KEY'),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    model="qwen-max",
    temperature=0.1
)

# 用户引导状态管理
user_session_state = {}


# 启动用户会话工具
@tool
def start_user_session(user_input: str) -> Dict[str, Any]:
    """
    启动用户会话流程，询问用户需要解决的问题

    参数:
        user_input: 用户的初始问题描述

    返回:
        dict: 包含会话状态的字典
        {
            "session_id": str,          # 会话ID
            "user_problem": str,        # 用户描述的问题
            "next_step": str,           # 下一步需要的信息
            "message": str               # 给用户的提示消息
        }
    """
    session_id = f"session_{random.randint(1000, 9999)}_{datetime.now().strftime('%Y%m%d%H%M%S')}"
    user_session_state[session_id] = {
        "problem": user_input,
        "step": "get_identifier"
    }

    return {
        "session_id": session_id,
        "user_problem": user_input,
        "next_step": "get_identifier",
        "message": "感谢您描述问题！为了查询您的订单信息，请提供您的手机号或身份证号。"
    }


# 获取用户标识工具
@tool
def get_user_identifier(session_id: str, identifier: str) -> Dict[str, Any]:
    """
    获取用户手机号或身份证号，并验证用户身份

    参数:
        session_id: 会话ID
        identifier: 用户提供的手机号或身份证号

    返回:
        dict: 包含验证结果的字典
        {
            "session_id": str,
            "identifier": str,
            "user_found": bool,
            "user_id": Optional[int],
            "message": str
        }
    """
    if session_id not in user_session_state:
        return {
            "session_id": session_id,
            "identifier": identifier,
            "user_found": False,
            "user_id": None,
            "message": "无效的会话ID，请重新开始会话。"
        }

    # 检查标识符类型
    if len(identifier) == 11 and identifier.isdigit():  # 手机号
        user = login_models.UserModel.objects.filter(phone=identifier).first()
    elif len(identifier) == 18:  # 身份证号
        user = login_models.UserModel.objects.filter(auth__id_number=identifier).first()
    else:
        return {
            "session_id": session_id,
            "identifier": identifier,
            "user_found": False,
            "user_id": None,
            "message": "请提供11位手机号或18位身份证号。"
        }

    if user:
        user_session_state[session_id]["user_id"] = user.id
        user_session_state[session_id]["step"] = "query_orders"
        return {
            "session_id": session_id,
            "identifier": identifier,
            "user_found": True,
            "user_id": user.id,
            "message": "身份验证成功！正在查询您的订单信息..."
        }
    else:
        return {
            "session_id": session_id,
            "identifier": identifier,
            "user_found": False,
            "user_id": None,
            "message": "未找到匹配的用户信息，请确认您提供的手机号或身份证号是否正确。"
        }


# 查询订单信息工具
@tool
def query_orders_with_orm(user_id: int) -> List[Dict[str, Any]]:
    """
    使用ORM查询用户的订单信息

    参数:
        user_id: 用户ID

    返回:
        list: 订单信息字典列表
        [
            {
                "order_id": str,
                "order_status": str,
                "order_price": Decimal,
                "order_time": datetime,
                "product_name": str,
                "product_price": Decimal
            },
            ...
        ]
    """
    try:
        # 使用ORM查询关联数据
        orders = orders_models.Order.objects.filter(
            order_user_id=user_id
        ).select_related('order_product')

        order_list = []
        for order in orders:
            order_list.append({
                "order_id": order.order_id,
                "order_status": order.order_status,
                "order_price": order.order_price,
                "order_time": order.order_time.strftime("%Y-%m-%d %H:%M:%S"),
                "product_name": order.order_product.name,
                "product_price": order.order_product.price
            })

        return order_list

    except Exception as e:
        return [{
            "error": f"查询失败: {str(e)}",
            "user_id": user_id
        }]


# 保险合同生成工具
@tool
def create_insurance_contract(
        aname, bname, acard_id, bcard_id,
        phone, relationship, effective_date=None, term_years=1
):
    """
    保险合同生成工具，根据用户提供的投保信息生成标准保险合同

    参数:
        aname: 投保人姓名
        bname: 被保人姓名
        acard_id: 投保人身份证号(18位)
        bcard_id: 被保人身份证号(18位)
        phone: 投保人联系方式
        relationship: 投保人与被保人关系(默认:"本人")
        effective_date: 保单生效日期(YYYY-MM-DD，默认当前日期+7天)
        term_years: 保险期限(年)(默认:1)

    返回:
        dict: 包含合同内容和状态的字典
        {
            "success": bool,            # 是否成功生成合同
            "contract_id": str,         # 合同编号
            "contract_content": dict,   # 合同内容详情
            "user_info": dict,          # 用户验证信息
            "product_info": dict,       # 产品信息
            "error_message": str,      # 错误信息(如果有)
            "generated_at": str         # 合同生成时间
        }
    """
    # 初始化返回结果
    result = {
        "success": False,
        "contract_id": "",
        "contract_content": {},
        "user_info": {},
        "product_info": {},
        "error_message": "",
        "generated_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    }

    try:
        # 1. 验证用户信息
        user_data = login_models.UserModel.objects.filter(phone=phone).first()
        if not user_data:
            result["error_message"] = "用户不存在"
            return result

        use_id = user_data.id
        check_phone = user_data.phone
        # 检查用户是否有实名认证信息
        if not user_data.auth:
            result["error_message"] = "用户未完成实名认证"
            return result

        is_card = user_data.auth.id_number

        # 2. 验证手机号和身份证号
        if phone != check_phone:
            result["error_message"] = "手机号不匹配"
            return result

        if is_card != acard_id:
            result["error_message"] = "投保人身份证号不匹配"
            return result

        # 3. 获取产品信息
        order = orders_models.Order.objects.filter(order_user_id=use_id, order_status='未审核').first()
        if not order:
            result["error_message"] = "未找到待审核的订单"
            return result

        product = order.order_product
        product_type = product.category
        coverage_amount = product.coverage_amount

        # 4. 验证必填字段
        if not all([aname, bname, acard_id, bcard_id, phone, relationship]):
            result["error_message"] = "请输入完整信息"
            return result

        # 5. 验证身份证号格式
        if len(acard_id) != 18 or len(bcard_id) != 18:
            result["error_message"] = "身份证号必须为18位"
            return result

        # 6. 验证关系类型
        valid_relationships = ["本人", "配偶", "子女", "父母"]
        if relationship not in valid_relationships:
            result["error_message"] = f"关系类型无效，应为{valid_relationships}之一"
            return result

        # 7. 设置默认生效日期(7天后)
        if not effective_date:
            effective_date = (datetime.now() + timedelta(days=7)).strftime("%Y-%m-%d")

        # 8. 验证生效日期
        try:
            eff_date = datetime.strptime(effective_date, "%Y-%m-%d")
            today = datetime.now()

            if eff_date.date() < today.date():
                result["error_message"] = "生效日期不能早于当前日期"
                return result

            if (eff_date.date() - today.date()).days > 30:
                result["error_message"] = "生效日期不能超过30天后"
                return result
        except ValueError:
            result["error_message"] = "日期格式无效(应为YYYY-MM-DD)"
            return result

        # 9. 生成合同编号(示例: IC-年月日-随机4位)
        contract_id = f"IC-{datetime.now().strftime('%Y%m%d')}-{str(random.randint(1000, 9999))}"

        # 10. 构建合同内容
        contract_content = {
            "contract_info": {
                "contract_id": contract_id,
                "generated_at": result["generated_at"],
                "effective_date": effective_date,
                "expiry_date": (eff_date + timedelta(days=term_years * 365)).strftime("%Y-%m-%d"),
                "product_type": product_type,
                "coverage_amount": coverage_amount,
                "term_years": term_years,
                "status": "待签署"
            },
            "applicant_info": {
                "name": aname,
                "id_number": acard_id,
                "phone": phone,
                "user_id": use_id
            },
            "insured_info": {
                "name": bname,
                "id_number": bcard_id,
                "relationship": relationship
            },
            "clauses": [
                "本保险合同依据《中华人民共和国保险法》及相关法律法规订立",
                f"投保人{aname}自愿为被保人{bname}投保本保险",
                f"保险金额为人民币{coverage_amount}元整",
                f"保险期限为{term_years}年，自{effective_date}起至{(eff_date + timedelta(days=term_years * 365)).strftime('%Y-%m-%d')}止",
                "具体保险责任和责任免除详见保险条款"
            ],
            "signature_required": {
                "applicant": False,
                "insured": relationship != "本人"
            }
        }

        # 11. 保存用户和产品信息到结果
        result.update({
            "user_info": {
                "user_id": use_id,
                "phone": phone,
                "id_number": acard_id
            },
            "product_info": {
                "product_id": product.id,
                "product_type": product_type,
                "coverage_amount": coverage_amount,
                "order_id": order.id
            }
        })

        # 12. 返回成功结果
        result.update({
            "success": True,
            "contract_id": contract_id,
            "contract_content": contract_content
        })

    except Exception as e:
        result["error_message"] = f"合同生成失败: {str(e)}"
        import traceback
        traceback.print_exc()

    return result


# 保险资料审核工具
@tool
def insurance_application_audit(application_data, strict_mode=True):
    """
    保险投保资料审核工具，验证投保申请的完整性和合规性

    参数:
        application_data: 投保资料字典，必须包含:
            - policy_effective_date: 保单生效时间(YYYY-MM-DD)
            - applicant: 投保人信息(dict)
                - name: 姓名
                - id_number: 证件号
                - contact: 联系方式
            - insured: 被保人信息(dict)
                - name: 姓名
                - id_number: 证件号
                - relationship: 与投保人关系
        strict_mode: 是否启用严格模式(默认True)

    返回:
        dict: 审核结果
        {
            "is_approved": bool,           # 是否通过审核
            "rejection_reasons": list,     # 拒绝原因列表
            "missing_fields": list,        # 缺失字段列表
            "validation_details": dict,    # 各字段验证详情
            "suggestions": list            # 改进建议
        }
    """
    results = {
        "is_approved": True,
        "rejection_reasons": [],
        "missing_fields": [],
        "validation_details": {},
        "suggestions": []
    }
    # 1. 检查必需字段是否存在
    required_fields = [
        "policy_effective_date",
        "applicant",
        "insured"
    ]
    applicant_required = ["name", "id_number", "contact"]
    insured_required = ["name", "id_number", "relationship"]

    # 检查顶级必需字段
    for field in required_fields:
        if field not in application_data:
            results["missing_fields"].append(field)
            results["is_approved"] = False

    # 检查投保人信息
    if "applicant" in application_data:
        for field in applicant_required:
            if field not in application_data["applicant"]:
                results["missing_fields"].append(f"applicant.{field}")
            else:
                # 验证身份证号格式(简单示例)
                if field == "id_number" and len(application_data["applicant"][field]) != 18:
                    results["validation_details"][f"applicant.{field}"] = "证件号长度不符"

    # 检查被保人信息
    if "insured" in application_data:
        for field in insured_required:
            if field not in application_data["insured"]:
                results["missing_fields"].append(f"insured.{field}")
            elif field == "relationship":
                valid_relationships = ["本人", "配偶", "子女", "父母"]
                if application_data["insured"][field] not in valid_relationships:
                    results["validation_details"][f"insured.{field}"] = f"关系类型无效，应为{valid_relationships}"

    # 2. 验证生效时间
    if "policy_effective_date" in application_data:
        try:
            effective_date = datetime.strptime(application_data["policy_effective_date"], "%Y-%m-%d")
            today = datetime.now()

            # 生效日期不能早于当前日期
            if effective_date.date() < today.date():
                results["validation_details"]["policy_effective_date"] = "生效日期不能早于当前日期"
                results["is_approved"] = False

            # 严格模式下：生效日期不能超过30天后
            if strict_mode and (effective_date.date() - today.date()).days > 30:
                results["validation_details"]["policy_effective_date"] = "生效日期不能超过30天后"
                results["suggestions"].append("请确认生效日期是否合理")

        except ValueError:
            results["validation_details"]["policy_effective_date"] = "日期格式无效(应为YYYY-MM-DD)"
            results["is_approved"] = False

    # 3. 综合判断
    if results["missing_fields"]:
        results["rejection_reasons"].append(f"缺少必要字段: {', '.join(results['missing_fields'])}")

    if results["validation_details"]:
        reasons = [f"{k}: {v}" for k, v in results["validation_details"].items()]
        results["rejection_reasons"].extend(reasons)

    return results


# 订单状态更新工具
@tool
def update_order_status(phone: str) -> Dict[str, Any]:
    """
    更新订单状态工具，当保险申请审核通过后，将订单状态从'未审核'改为'已审核'

    参数:
        phone: 投保人手机号(用于标识用户)

    返回:
        dict: 包含操作结果的字典
        {
            "success": bool,       # 操作是否成功
            "message": str,        # 结果消息
            "user_id": int,       # 用户ID(如果找到)
            "updated_count": int,  # 更新的订单数量
            "error": str          # 错误信息(如果有)
        }
    """
    result = {
        "success": False,
        "message": "",
        "user_id": None,
        "updated_count": 0,
        "error": ""
    }

    try:
        # 1. 验证并获取用户信息
        if not phone or len(phone) != 11:
            result["message"] = "无效的手机号格式"
            result["error"] = "手机号必须为11位数字"
            return result

        user_data = login_models.UserModel.objects.filter(phone=phone).first()
        if not user_data:
            result["message"] = "用户不存在"
            return result

        user_id = user_data.id
        result["user_id"] = user_id

        # 2. 执行订单状态更新
        updated_count = orders_models.Order.objects.filter(
            order_user_id=user_id,
            order_status='未审核'
        ).update(order_status='已审核,未支付')

        result["updated_count"] = updated_count

        if updated_count > 0:
            result["success"] = True
            result["message"] = f"成功更新{updated_count}条订单状态为'已审核'"
        else:
            result["message"] = "没有找到待审核的订单"

    except Exception as e:
        result["error"] = str(e)
        result["message"] = "订单状态更新失败"
        # 记录完整错误堆栈
        import traceback
        traceback.print_exc()

    return result


# 更新系统提示模板
SYSTEM_PROMPT = """您是一名专业的保险核保助手，负责处理用户查询和保险申请。
工作流程：
1. 首先使用start_user_session启动会话，询问用户需要解决的问题
2. 使用get_user_identifier获取并验证用户手机号或身份证号
3. 使用query_orders_with_orm查询用户订单信息
4. 根据用户需求提供解决方案
5. 如需生成合同，使用insurance_application_audit审核投保资料
6. 审核通过后使用create_insurance_contract生成合同
7. 若审核不通过，需明确告知用户原因
8. 若审核通过使用update_order_status更新订单状态

请确保：
1. 用户引导流程清晰：先了解问题 → 获取身份信息 → 提供服务
2. 身份验证严格：必须验证手机号/身份证号的有效性
3. 订单查询准确：使用ORM确保数据关联正确
4. 合同生成规范：遵循保险条款要求

新增用户引导规则：
- 首次交互必须询问用户需要解决什么问题
- 用户描述问题后，必须要求提供手机号或身份证号
- 验证身份后才可提供订单查询或合同生成服务
"""

# 创建对话提示模板
prompt = ChatPromptTemplate.from_messages([
    SystemMessage(content=SYSTEM_PROMPT),
    MessagesPlaceholder(variable_name="chat_history", optional=True),
    HumanMessagePromptTemplate.from_template("{input}"),
    MessagesPlaceholder(variable_name="agent_scratchpad")
])

# 准备工具列表（新增会话管理工具）
tools = [
    start_user_session,
    get_user_identifier,
    query_orders_with_orm,
    insurance_application_audit,
    create_insurance_contract,
    update_order_status,
    retriever_tool
]

# 创建函数型Agent
agent = create_openai_functions_agent(
    llm=llm,
    prompt=prompt,
    tools=tools
)

# 创建Agent执行器
agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    verbose=True,
    handle_parsing_errors=True
)

if __name__ == "__main__":
    # 模拟完整流程
    response = agent_executor.invoke({
        "input": "我想查询我的订单状态",
        "chat_history": []
    })
    print("初始响应:", response["output"])

    # 模拟用户提供手机号
    if "请提供您的手机号或身份证号" in response["output"]:
        session_id = "模拟会话ID"
        response = agent_executor.invoke({
            "input": f"我的手机号是19139230505, 会话ID: {session_id}",
            "chat_history": response["chat_history"]
        })
        print("身份验证结果:", response["output"])

        # 模拟查询订单
        if "正在查询您的订单信息" in response["output"]:
            response = agent_executor.invoke({
                "input": f"查询订单, 会话ID: {session_id}",
                "chat_history": response["chat_history"]
            })
            print("订单查询结果:", response["output"])